package com.hup.htts.view;

import com.hup.htts.config.BeanConfig;
import com.hup.htts.model.MainConfig;
import com.hup.htts.presenter.MainPresenter;
import com.hup.htts.service.GlobalKeyService;
import com.hup.htts.service.tts.TTSService;
import com.hup.htts.service.tts.jna.VoiceInfo;
import com.hup.htts.view.setting.SettingDialog;
import com.hup.utils.commons.start.SpringContext;
import com.hup.utils.commons.start.StartupInfo;
import com.hup.utils.swing.FrameUtil;
import com.hup.utils.swing.FrameUtil.Gravity;
import com.hup.utils.swing.frame.BaseJWindow;
import com.hup.utils.swing.frame.SingletonWindowHelper;
import com.hup.utils.swing.frame.WindowEdgeHideHelper;
import com.hup.utils.swing.frame.WindowEdgeHideHelper.EdgeHideWindow;
import com.hup.utils.swing.frame.WindowLocationAdjustor;
import com.hup.utils.swing.frame.WindowLocationAdjustor.WindowLocationAdjustorCallback;
import com.hup.utils.swing.model.BaseWindowConfig;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;

import javax.swing.DefaultComboBoxModel;
import java.awt.Component;
import java.awt.Point;
import java.awt.Window;
import java.util.ArrayList;
import java.util.Vector;

/**
 * @author hugan
 * @date 2021/9/12
 */
@Log4j2
public class MainWindow extends BaseJWindow implements EdgeHideWindow {

    private GlobalKeyService globalKeyService;
    private final MainPresenter presenter;
    private final MainConfig config;
    private final TTSService ttsService;
    private MainForm form;

    @Getter
    private WindowEdgeHideHelper edgeHideHelper;
    private boolean inited;

    public MainWindow() {
        super(StartupInfo.getApplicationChName());
        this.globalKeyService = SpringContext.getBean(BeanConfig.GLOBAL_KEY_SERVICE, GlobalKeyService.class);
        presenter = SpringContext.getBean(MainPresenter.class);
        ttsService = SpringContext.getBean(TTSService.class);
        config = SpringContext.getBean(MainConfig.class);

        initView();
        initListener();
        initConfig();
        inited = true;
    }

    private void initView() {
        form = new MainForm();
        setContentPane(form.root);
        form.txtTitle.setText(getTitle());

        setAlwaysOnTop(true);
        pack();
        FrameUtil.setLocation(this, Gravity.TOP_CENTER);
    }

    private void initListener() {
        WindowLocationAdjustor.bind(new LocationHandler());
        edgeHideHelper = WindowEdgeHideHelper.bind(this);
        //
        form.btnSetting.setActionListener(e -> {
            notifyMouseExited();
            SettingDialog window = SingletonWindowHelper.getWindow(SettingDialog.class);
            if (window == null) {
                window = new SettingDialog();
            }
            window.setVisible(true);
        });
        form.btnHide.setActionListener(e -> switchVisible(false));
        form.btnExit.setActionListener(confirm("退出", () -> {
            dispose();
            presenter.doExit();
        }));
        //
        form.cbbVoice.addActionListener(e -> {
            if (!inited) return;
            int selectedIndex = form.cbbVoice.getSelectedIndex();
            log.info("selectedIndex={}", selectedIndex);
            ttsService.setVoice(selectedIndex);
            config.voiceIndex = selectedIndex;
            config.save();
        });
        form.slSpeed.addChangeListener(e -> {
            if (!inited) return;
            int value = form.slSpeed.getValue();
            log.info("value={}, Adjusting={}", value, form.slSpeed.getValueIsAdjusting());
            if (!form.slSpeed.getValueIsAdjusting()) return;
            ttsService.setRate(value);
            config.voiceSpeed = value;
            config.save();
        });
        form.btnSpeak.setActionListener(e -> {
            boolean selected = form.btnSpeak.isSelected();
            if (selected) {
                globalKeyService.startListen();
            } else {
                globalKeyService.stopListen();
                ttsService.stop();
            }
        });
    }

    private void initConfig() {
        BaseWindowConfig windowConfig = config.windowConfig;
        if (windowConfig.loc != null) setLocation(windowConfig.loc);
        int rate = TTSService.getSafeRate(config.voiceSpeed);
        form.slSpeed.setValue(rate);
        ttsService.setRate(rate);
    }

    /**
     * 查询到语音引擎,只会被调用一次!
     */
    public void onGetVoices(ArrayList<VoiceInfo> voiceInfos) {
        log.info("voiceInfos.size={}", voiceInfos.size());
        if (voiceInfos.isEmpty()) {
            onExecuteException("获取语音引擎", new IllegalArgumentException("数量为0"));
            return;
        }
        //应用配置中的引擎
        int voiceIndex = 0;
        if (config.voiceIndex >= 0 && config.voiceIndex < voiceInfos.size()) {
            voiceIndex = config.voiceIndex;
            log.info("还原配置voiceIndex={}", voiceIndex);
        }
        ttsService.setVoice(voiceIndex);

        //更新ui
        Vector<String> items = new Vector<>(voiceInfos.size());
        for (VoiceInfo voiceInfo : voiceInfos) {
            String name = voiceInfo.name.toString();
            name = name.replace("TTS_MS_", "");
            items.add(name);
        }
        DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>(items);
        model.setSelectedItem(items.get(voiceIndex));
        form.cbbVoice.setModel(model);
        //form.cbbVoice.setSelectedIndex(voiceIndex);//这回触发监听回调
    }

    private class LocationHandler implements WindowLocationAdjustorCallback {

        @Override
        public Window getWindow() {
            return MainWindow.this;
        }

        @Override
        public Component[] getAdjustor() {
            return new Component[]{form.root};
        }

        @Override
        public void afterMoved(int x, int y, Boolean onTop, Boolean onLeft) {
            if (config.windowConfig.loc == null) config.windowConfig.loc = new Point();
            config.windowConfig.loc.x = x;
            config.windowConfig.loc.y = y;
            config.save();
        }

    }

}
